#pragma once
#include "Socket.hpp"
#include <iostream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>
#include <functional>

using namespace SocketModule;

class Request
{
public:
    Request()
    {
    }
    Request(int x, int y, char oper) : _x(x), _y(y), _oper(oper)
    {
    }
    std::string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper; // _oper是char，也是整数，ASCII

        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt(); //?
        }
        return ok;
    }
    ~Request() {}
    int X() { return _x; }
    int Y() { return _y; }
    char Oper() { return _oper; }

private:
    int _x;
    int _y;
    char _oper; // + - * / % -> _x _oper _y -> 10 + 20
};

class Response
{
public:
    Response() {}
    Response(int result, int code) : _result(result), _code(code)
    {
    }
    std::string Serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::FastWriter writer;
        return writer.write(root);
    }
    bool Deserialize(std::string& in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
        }
        return ok;
    }
    ~Response() {}
    void SetResult(int res)
    {
        _result = res;
    }
    void SetCode(int code)
    {
        _code = code;
    }
    void ShowResult()
    {
        std::cout << "计算结果是: " << _result << "[" << _code << "]" << std::endl;
    }

private:
    int _result; // 运算结果，无法区分清楚应答是计算结果，还是异常值
    int _code;   // 0:sucess, 1,2,3,4->不同的运算异常的情况, 约定！！！！
};

const std::string sep = "\r\n";
using func_t = std::function<Response(Request& req)>;
//解决两个问题1.序列和反序列化2.解决TCP的半包，黏包问题
class Protocol
{
    public:
    Protocol()
    {}

    Protocol(func_t func):_func(func)
    {}

    std::string Encode(const std::string& jsonstr)
    {
        //为json串添加长度字段用于数据分离
        std::string len = std::to_string(jsonstr.size());
        return len + sep + jsonstr + sep;
    }

    bool Decode(std::string& buffer, std::string* package)
    {
        size_t pos = buffer.find(sep);
        if (pos == std::string::npos)
            return false;//缓存区一定没有一个完整的报文
        std::string package_len_str = buffer.substr(0, pos);//截取长度标识
        int package_len_int = std::stoi(package_len_str);
        int target_len = package_len_str.size() + package_len_int + 2 * sep.size();
        if (buffer.size() < target_len)
            return false;
        //到这里说明一定至少有一个完整报文
        *package = buffer.substr(pos + sep.size(), package_len_int);
        //移除缓冲区中的该报文，不影响下一次Decode
        buffer.erase(0, target_len);
        return true;
    }
    void GetRequest(std::shared_ptr<Socket>& sock, InetAddr& client)
    {
        std::string buffer_queue;//缓冲区队列
        while (true)
        {
            int n = sock->Recv(&buffer_queue);
            if (n > 0)
            {
                std::string json_package;
                //1.解析缓冲区获得一个个的json请求
                while (Decode(buffer_queue, &json_package))
                {
                    //2.进到这里拿到了一个完整的json串，反序列化
                    LOG(LogLevel::DEBUG) << client.StringAddr() << " 请求: " << json_package;
                    Request req;
                    bool ok = req.Deserialize(json_package);
                    if (!ok)
                        continue;
                    //3.对解析json串得到的request进行处理
                    Response resp = _func(req);

                    //4.对request序列化
                    std::string json_str = resp.Serialize();

                    //5.对json串进行encode
                    std::string send_str = Encode(json_str);;

                    //6.直接发送
                    sock->Send(send_str);

                }
            }
            else if (n == 0)
            {
                LOG(LogLevel::INFO) << "client:" << client.StringAddr() << "Quit!";
                break;
            }
            else
            {
                LOG(LogLevel::WARNING) << "client:" << client.StringAddr() << ", recv error";
                break;
            }
        }
    }    
        bool GetResponse(std::shared_ptr<Socket> &client, std::string & resp_buff, Response * resp)
        {
            // 面向字节流,你怎么保证，你的client读到的 一个网络字符串，就一定是一个完整的请求呢？？
            while (true)
            {
                int n = client->Recv(&resp_buff);
                if (n > 0)
                {
                    std::string json_package;
                    while (Decode(resp_buff, &json_package))
                    {
                        resp->Deserialize(json_package);
                    }
                    return true;
                }
                else if (n == 0)
                {
                    std::cout << "server quit " << std::endl;
                    return false;
                }
                else
                {
                    std::cout << "recv error" << std::endl;
                    return false;
                }
            }
        }

        std::string BuildRequestString(int x, int y, char oper)
        {
            // 1. 构建一个完整的请求
            Request req(x, y, oper);

            // 2. 序列化
            std::string json_req = req.Serialize();
            // 3. 添加长度报头
            return Encode(json_req);
        }

        ~Protocol(){}
private:
    func_t _func;//回调处理，应用层！！
};